package matheus.tp01cg.objetosdedesenho;

import android.graphics.Bitmap;
import android.graphics.Color;

/**
 * Classe base para os tipos de desenhos
 * 
 * @author matheus
 * 
 */
public abstract class ObjetoDeDesenho implements Cloneable {
	/**
	 * Desenha o objeto na matriz de pixels (bitmap)
	 * 
	 * @param bitmap
	 */
	public abstract void desenha(Bitmap bitmap);

	/**
	 * Rotaciona o objeto baseado em um ponto de referencia e no angulo (em
	 * radianos)
	 * 
	 * @param centro
	 *            Ponto de referencia para rotacao
	 * @param angulo
	 *            Em radianos
	 */
	public abstract void rotaciona(Coords centro, double angulo);

	/**
	 * Realiza rotacao utilizando o centro do objeto como ponto de referencia
	 * 
	 * @param angulo
	 *            Em radianos
	 */
	public void rotaciona(double angulo) {
		rotaciona(getCentro(), angulo);
	}

	/**
	 * Translacao do ObjetoDeDesenho
	 * 
	 * @param x
	 *            Deslocamento no eixo X (em Pixels)
	 * @param y
	 *            Deslocamento no eixo Y (em Pixels)
	 */
	public abstract void translada(int x, int y);

	/**
	 * Redimensionamento do ObjetoDeDesenho
	 * 
	 * @param ref
	 *            Ponto de referencia
	 * @param x
	 *            Fator de escala no eixo X (< 1.0 reducao, > 1.0 ampliacao)
	 * @param y
	 *            Fator de escala no eixo Y (< 1.0 reducao, > 1.0 ampliacao)
	 */
	public abstract void escala(Coords ref, double x, double y);

	/**
	 * Redimensionamento do ObjetoDeDesenho utilizando o centro do mesmo como
	 * ponto de referencia
	 * 
	 * @param x
	 *            Fator de escala no eixo X (< 1.0 reducao, > 1.0 ampliacao)
	 * @param y
	 *            Fator de escala no eixo Y (< 1.0 reducao, > 1.0 ampliacao)
	 */
	public void escala(double x, double y) {
		escala(getCentro(), x, y);
	}

	/**
	 * Redimensionamento do ObjetoDeDesenho por um fator a ser aplicado em ambos
	 * os eixos (x, y) utilizando o centro do objeto como ponto de referencia
	 * 
	 * @param fator
	 *            (< 1.0 reducao, > 1.0 ampliacao)
	 */
	public void escala(double fator) {
		escala(fator, fator);
	}

	/**
	 * Obtem o minimo valor no o eixo X de um ponto que intercepta o
	 * ObjetoDeDesenho
	 */
	public abstract int getMinX();

	/**
	 * Obtem o minimo valor no o eixo Y de um ponto que intercepta o
	 * ObjetoDeDesenho
	 */
	public abstract int getMinY();

	/**
	 * Obtem o maximo valor no o eixo X de um ponto que intercepta o
	 * ObjetoDeDesenho
	 */
	public abstract int getMaxX();

	/**
	 * Obtem o maximo valor no o eixo Y de um ponto que intercepta o
	 * ObjetoDeDesenho
	 */
	public abstract int getMaxY();

	public Coords getMax() {
		return new Coords(getMaxX(), getMaxY());
	}

	public Coords getMin() {
		return new Coords(getMinX(), getMinY());
	}

	/**
	 * Obtem a coordenada de centro do ObjetoDeDesenho
	 */
	public Coords getCentro() {
		int maxX = getMaxX();
		int minX = getMinX();
		int maxY = getMaxY();
		int minY = getMinY();
		int xCentro = ((maxX - minX) / 2) + minX;
		int yCentro = ((maxY - minY) / 2) + minY;
		return new Coords(xCentro, yCentro);
	}

	/**
	 * Realiza uma copia do ObjetoDeDesenho
	 */
	@Override
	public abstract Object clone() throws CloneNotSupportedException;

	public abstract boolean intercepta(Coords ponto, int raio);

	protected int corContorno;

	public int getCorContorno() {
		return corContorno;
	}

	public void setCorContorno(int corContorno) {
		this.corContorno = corContorno;
	}

	/**
	 * Limpa o contorno do objeto no bitmap desenhando-o por cima em cor
	 * transparente. Isto ira limpar qualquer area do bitmap q seja de outro
	 * objeto de desenho cuja o contorno do objeto em questao intercepte.
	 */
	public void limpaBorda(Bitmap bitmap) {
		int corContorno = this.corContorno;
		this.corContorno = Color.TRANSPARENT;
		desenha(bitmap);
		this.corContorno = corContorno;
	}

	public void redesenhar(Bitmap bitmap) {
		limpaBorda(bitmap);
		desenha(bitmap);
	}

	protected int espessuraBorda = 1;

	/**
	 * @return the espessuraBorda
	 */
	public int getEspessuraBorda() {
		return espessuraBorda;
	}

	/**
	 * @param espessuraBorda
	 *            the espessuraBorda to set
	 */
	public void setEspessuraBorda(int espessuraBorda) {
		this.espessuraBorda = espessuraBorda;
	}

	protected static void bitmapSetPonto(Bitmap bitmap, int x, int y, int cor,
			int raio) {
		int metade = raio / 2;
		int limiteInferior = metade * -1;
		int limeteSuperior = metade + (raio % 2);
		int novoX, novoY;
		for (int i = limiteInferior; i < limeteSuperior; i++) {
			for (int j = limiteInferior; j < limeteSuperior; j++) {
				novoX = x + i;
				novoY = y + j;
				if (novoX >= 0 && novoX < bitmap.getWidth() && novoY >= 0
						&& novoY < bitmap.getHeight())
					bitmap.setPixel(novoX, novoY, cor);
			}
		}
	}
}
